#ifndef _GM_MONITOR_H
#define _GM_MONITOR_H

#include <stdint.h>
#include <string.h>
#include <unistd.h>

#include "gm_file.h"
#include "cJSON.h"
#include "list.h"

#define MAX_LEN_NAME 512

struct monitor_info_interface
{
	char* (*update)(timely_file *tf);
	void (*parse_text)(void*, void *, char*);
	void* user_data;
	void* user_param;
};

typedef struct _monitor_info
{
	timely_file file_stat;
	char name[MAX_LEN_NAME];
	char buffer[BUFFSIZE];
	uint32_t  buffer_len;
	uint8_t   type;
	struct monitor_info_interface oper;
} monitor_node, *p_monitor_node;

typedef struct _task
{
	//private
	struct list_head thisnode;
	int  (*init)(p_monitor_node*, const char*);
	void (*update)(p_monitor_node*);
	void (*to_json)(cJSON*);
	uint32_t (*to_text)(char*, uint32_t);
	void (*clean)(void);
	void (*correction)(const char*);
	p_monitor_node mn;

	// user data
	const char* (*correction_value)(void);
	char name[8];
	cJSON *json;
	char* ignore;
	uint16_t uf;
	uint16_t cu;
} task, *ptask;

#define TO_STRING(x) #x
#define ADD_MOD_EXT(mod, key, _correction_value, _ignore, _uf) \
	task mod = {.name = #key, \
	.correction_value = _correction_value}; \
	mod##_task_init(&mod, _ignore, _uf);

#define ADD_MOD(mod, key, _ignore) ADD_MOD_EXT(mod, key, NULL, _ignore, 0)
#define ADD_MOD_2(mod, key, corr, _ignore) ADD_MOD_EXT(mod, key, corr, _ignore, 0)

#define INIT_MODE(mod) mod.init(&(mod.mn), mod.ignore);
#define UPDATE_MOD(mod) \
	mod.update(&(mod.mn)); \
	if (mod.correction_value && mod.correction) { \
		mod.correction(mod.correction_value()); \
	}
#define UPDATE_MOD_JSON(mod, root) \
	UPDATE_MOD(mod) \
	if (mod.json == NULL) { \
		mod.json = cJSON_CreateObject(); \
		cJSON_AddItemToObject(root, mod.name, mod.json); \
	} \
	mod.to_json(mod.json);
#define UPDATE_MOD_TEXT(mod, BUFFER, SIZE) \
	UPDATE_MOD(mod) \
	if (mod.to_text) { \
		mod.to_text(BUFFER, SIZE); \
	} \
	mod.to_json(mod.json);

#define CLENA_MOD(mod) \
	mod.clean(); \
	free(mod.mn);

#define ADD_MOD_LIST(mod, key, list, _ignore) \
	ADD_MOD(mod, key, _ignore) \
	list_add_tail(&(mod.thisnode), list);
#define ADD_MOD_LIST_2(mod, key, corr, list, _ignore) \
	ADD_MOD_2(mod, key, corr, _ignore) \
	list_add_tail(&(mod.thisnode), list);

void init_monitor_list_node(struct list_head* list);
void update_monitor_list_node(struct list_head* list, cJSON* root);
void update_monitor_list_node_text(struct list_head* list, char* buffer, uint32_t size);
void clean_monitor_list_node(struct list_head* list);

#endif
